// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

#ifndef CERT_DEVICE_HW_H_
#define CERT_DEVICE_HW_H_

#include <stdint.h>
#include "status/rot_status.h"
#include "crypto/hash.h"


/**
 * A platform-independent API for providing hooks to the hardware controlled certificate validation
 * information.
 */
struct cert_device_hw {
	/**
	 * Verify that the root key for the certificate is a valid key.
	 *
	 * @param hw The device hardware to query for root key validation.
	 * @param root_key The root key information to verify.
	 * @param key_length The length of the root key data.
	 * @param hash The hashing engine to use for verification.
	 *
	 * @return 0 if the root key is valid or an error code.  CERT_DEVICE_HW_BAD_ROOT_KEY should be
	 * returned if the root key is not valid.
	 */
	int (*verify_root_key) (struct cert_device_hw *hw, const uint8_t *root_key, size_t key_length,
		struct hash_engine *hash);

	/**
	 * Determine if the root key for the certificate is trusted by the hardware.
	 *
	 * @param hw THe device hardware to query.
	 * @param root_id The ID of the root key to check.
	 *
	 * @return 1 if the root key is trusted, 0 if not, or an error code.
	 */
	int (*is_root_key_trusted) (struct cert_device_hw *hw, int root_id);

	/**
	 * Get the minimum length allowed for signing keys.
	 *
	 * @param hw THe device hardware to query for key length requirements.
	 * @param key_length The buffer that will contains the minimum key length.  The key length will
	 * be reported in bits (i.e. 2048 for RSA2k).
	 *
	 * @return 0 if the minimum length was retrieved successfully or an error code.
	 */
	int (*get_minimum_key_length) (struct cert_device_hw *hw, size_t *key_length);

	/**
	 * Get the current certificate revocation identifier from the device.
	 *
	 * @param hw The device hardware to query for the revocation identifier.
	 * @param id The buffer that will contain the current revocation identifier.
	 *
	 * @return 0 if the revocation identifier was retrieved successfully or an error code.
	 */
	int (*get_revocation) (struct cert_device_hw *hw, uint32_t *id);

	/**
	 * Set the current certificate revocation identifier for the device.
	 *
	 * @param hw The device hardware that should update the revocation identifier.
	 * @param id The revocation identifier to set.
	 *
	 * @return 0 if the revocation identifier was successfully set or an error code.
	 */
	int (*set_revocation) (struct cert_device_hw *hw, uint32_t id);
};


#define	CERT_DEVICE_HW_ERROR(code)		ROT_ERROR (ROT_MODULE_CERT_DEVICE_HW, code)

/**
 * Error codes that can be generated by certificate management hardware.
 */
enum {
	CERT_DEVICE_HW_INVALID_ARGUMENT = CERT_DEVICE_HW_ERROR (0x00),		/**< Input parameter is null or not valid. */
	CERT_DEVICE_HW_NO_MEMORY = CERT_DEVICE_HW_ERROR (0x01),				/**< Memory allocation failed. */
	CERT_DEVICE_HW_VERIFY_ROOT_FAILED = CERT_DEVICE_HW_ERROR (0x02),	/**< The root key could not be verified. */
	CERT_DEVICE_HW_CHECK_ROOT_FAILED = CERT_DEVICE_HW_ERROR (0x03),		/**< Failed to check root key trust. */
	CERT_DEVICE_HW_GET_MIN_LENGTH_FAILED = CERT_DEVICE_HW_ERROR (0x04),	/**< Unable to determine the minimum required key length. */
	CERT_DEVICE_HW_GET_REVOKE_FAILED = CERT_DEVICE_HW_ERROR (0x05),		/**< Unable to get the revocation status. */
	CERT_DEVICE_HW_SET_REVOKE_FAILED = CERT_DEVICE_HW_ERROR (0x06),		/**< Unable to set the revocation status. */
	CERT_DEVICE_HW_BAD_ROOT_KEY = CERT_DEVICE_HW_ERROR (0x07),			/**< The root key is not valid. */
	CERT_DEVICE_HW_NOT_INIT = CERT_DEVICE_HW_ERROR (0x08),				/**< Hardware has not been initialized. */
	CERT_DEVICE_HW_UNSUPPORTED = CERT_DEVICE_HW_ERROR (0x09),			/**< Hardware does not support certificate functions. */
};


#endif /* CERT_DEVICE_HW_H_ */
